/*
 * Copyright 2006-2008 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.martinimix.webflow.action;

import java.util.Iterator;
import java.util.Set;

import net.martinimix.context.support.ReferenceDataService;
import net.martinimix.webflow.accessor.LocaleAccessor;
import net.martinimix.webflow.accessor.HttpServletRequestLocaleAccessor;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.validation.Errors;
import org.springframework.webflow.core.collection.AttributeMap;
import org.springframework.webflow.core.collection.LocalAttributeMap;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;

/**
 * Provides a simple form action implementation capable of providing
 * reference data to a view and interpreting transition exceptions.
 * 
 * @author Scott Rossillo
 *
 */
public class SimpleFormAction extends AbstractExceptionAwareFormAction {
	
	private final static Log log = LogFactory.getLog(SimpleFormAction.class);
	
	private ReferenceDataService referenceDataService;
	private Set referenceData;
	private LocaleAccessor localeAccessor = new HttpServletRequestLocaleAccessor();
	
	/**
	 * Creates a new simple form action.
	 */
	public SimpleFormAction() { }
	
	/**
	 * This implementation is empty.
	 * 
	 * @see net.martinimix.webflow.action.AbstractExceptionAwareFormAction#onException(java.lang.Exception, org.springframework.validation.Errors)
	 */
	public void onException(Exception ex, Errors errors) { }

	/* (non-Javadoc)
	 * @see org.springframework.webflow.action.FormAction#setupForm(org.springframework.webflow.execution.RequestContext)
	 */
	public final Event setupFormInternal(RequestContext context) throws Exception {
				
		context.getRequestScope().putAll(referenceData());
		
		return super.setupFormInternal(context);
	}
	
	/**
	 * Returns an attribute map containing reference data requested 
	 * for this form action.
	 * 
	 * @return a <code>AttributeMap</code> containing
	 * required reference data 
	 * 
	 * @see #setReferenceData(Set)
	 */
	protected final AttributeMap referenceData() {
		
		LocalAttributeMap data = new LocalAttributeMap();
	
		Iterator it;
		String key;
		
		if(referenceData != null) {
			it = referenceData.iterator();
			while(it.hasNext()) {
				key = (String) it.next();
				if(log.isDebugEnabled()) {
					log.debug("Setting form reference data [" + key + "]");
				}
				data.put(
						key,
						referenceDataService.getReferenceData(key));
			}
		}
		
		return data;
	}

	/**
	 * Returns the locale accessor for this form action.  By default
	 * an instance of {@link HttpServletRequestLocaleAccessor} is returned.
	 * This behavior can be overridden by registering a custom locale
	 * accessor with {@link #setLocaleAccessor(LocaleAccessor)}.
	 * 
	 * @return a <code>LocaleAccessor</code> for this form action
	 * 
	 * @see #setLocaleAccessor(LocaleAccessor)
	 */
	public final LocaleAccessor getLocaleAccessor() {
		return localeAccessor;
	}

	/**
	 * Sets the locale access for this form action.
	 * 
	 * @param localeAccessor the <code>LocaleAccessor</code> to be
	 * used by this form action
	 */
	public final void setLocaleAccessor(LocaleAccessor localeAccessor) {
		this.localeAccessor = localeAccessor;
	}

	/**
	 * Returns reference data identifiers this form action will define when setting
	 * up this form
	 *  
	 * @return the <code>Set</code> of reference data identifiers this form action will
	 * define when setting up forms
	 * 
	 */
	public Set getReferenceData() {
		return referenceData;
	}

	/**
	 * Sets the reference data this form action should define when setting up
	 * forms.
	 * 
	 * @see #setupForm(RequestContext)
	 */
	public void setReferenceData(Set referenceData) {
		this.referenceData = referenceData;
	}

	/**
	 * Sets the reference data service for this form action.
	 * 
	 * @param referenceDataService the <code>ReferenceDataService</code> this
	 * form action will use to provide reference data when setting up this form
	 */
	public final void setReferenceDataService(ReferenceDataService referenceDataService) {
		this.referenceDataService = referenceDataService;
	}
	
}
